package com.xtaller.sdboot.util;

import com.alibaba.fastjson.JSONObject;
import com.xtaller.sdboot.entity.IamApplicationPermission;
import com.xtaller.sdboot.entity.IamPermission;
import com.xtaller.sdboot.entity.IamRole;
import com.xtaller.sdboot.entity.IamRolePermission;
import com.xtaller.sdboot.service.*;
import com.xtaller.sdboot.utils.helper.StrHelper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author : Taller
 * @date : 2020/3/6 08:59
 * @Description : 权限工具
 */
@Component
public class PermissionUtil {
    @Autowired private CacheUtil cacheUtil;
    @Autowired private IamApplicationPermissionService applicationPermissionService;
    @Autowired private IamPermissionService permissionService;
    @Autowired private IamRolePermissionService rolePermissionService;
    @Autowired private IamUserApplicationService userApplicationService;
    @Autowired private IamRoleService roleService;

    /**
     * 获取应用超管权限
     * */
    public List<IamPermission> getAppPermission(String appId){
        var cacheKey = "permission-app-" + appId;
        var list = cacheUtil.getList(cacheKey, IamPermission.class);
        if(list != null){
            return list;
        }
        var qw = new QueryWrapper<IamApplicationPermission>();
        qw.lambda().eq(IamApplicationPermission::getAppId, appId);
        var permissions = applicationPermissionService.getList(qw);
        if(permissions.size() == 0){
            return null;
        }
        var ids = permissions.stream().map(x -> x.getPermissionId()).collect(Collectors.toList());
        var permissionQw = new QueryWrapper<IamPermission>();
        permissionQw.lambda()
                .eq(IamPermission::getType, "admin")
                .in(IamPermission::getId, ids)
                .orderByDesc(IamPermission::getModuleId)
                .orderByDesc(IamPermission::getSortId)
                .orderByDesc(IamPermission::getParentId)
                .orderByDesc(IamPermission::getState)
                .orderByDesc(IamPermission::getGroups)
                .orderByDesc(IamPermission::getPosition);
        list = permissionService.getList(permissionQw);
        cacheUtil.set(cacheKey, list);
        return list;
    }
    /**
     * 修改app超管权限
     * */
    @Async("taskExecutor")
    public void updateAppPermission(String appId){
        var cacheKey = "permission-app-" + appId;
        cacheUtil.delete(cacheKey);
        getAppPermission(appId);
    }


    /**
     * 获取角色权限
     * */
    public List<IamPermission> getRolePermission(List<String> roleIds){
        List<IamPermission> list = new ArrayList<>();
        roleIds.stream().forEach(x -> {
            list.addAll(getPermissionByRoleId(x));
        });
        // 去重复
        var newList = list.stream().distinct().collect(Collectors.toList());
        // 排序
        var sortList = newList.stream().sorted(
                            Comparator.comparing(IamPermission::getModuleId, Comparator.reverseOrder())
                            .thenComparing(IamPermission::getSortId, Comparator.reverseOrder())
                            .thenComparing(IamPermission::getParentId)
                            .thenComparing(IamPermission::getState, Comparator.reverseOrder())
                            .thenComparing(IamPermission::getGroups)
                            .thenComparing(IamPermission::getPosition).reversed()
                    ).collect(Collectors.toList());
        return sortList;
    }
    private List<IamPermission> getPermissionByRoleId(String roleId){
        var cacheKey = "permission-role-" + roleId;
        var list = cacheUtil.getList(cacheKey, IamPermission.class);
        if(list != null){
            return list;
        }
        // 获取权限
        var rpQw = new QueryWrapper<IamRolePermission>();
        rpQw.lambda().eq(IamRolePermission::getRoleId, roleId);
        var rps = rolePermissionService.getList(rpQw);
        var permissionsIds = rps.stream().map(x -> x.getPermissionId()).collect(Collectors.toList())
                .stream().distinct().collect(Collectors.toList());
        var permissionQw = new QueryWrapper<IamPermission>();
        permissionQw.lambda()
                .eq(IamPermission::getType, "admin")
                .in(IamPermission::getId, permissionsIds)
                .orderByDesc(IamPermission::getModuleId)
                .orderByDesc(IamPermission::getSortId)
                .orderByDesc(IamPermission::getParentId)
                .orderByDesc(IamPermission::getState)
                .orderByDesc(IamPermission::getGroups)
                .orderByDesc(IamPermission::getPosition);
        list = permissionService.getList(permissionQw);
        cacheUtil.set(cacheKey, list);
        return list;
    }
    /**
     * 更新角色权限
     * */
    @Async("taskExecutor")
    public void updateRolePermission(String roleId){
        var cacheKey = "permission-role-" + roleId;
        cacheUtil.delete(cacheKey);
        getPermissionByRoleId(roleId);
    }

    /**
     * 设置用户的当前系统的用户类型和角色
     * */
    @Async("taskExecutor")
    public void updateAppCache(String uid, int isAdmin, List<String> roleIds){
        var cacheKey = "account-" + uid;
        var cache = cacheUtil.get(cacheKey, JSONObject.class);
        if(roleIds != null) {
            cache.put("role", StrHelper.join(roleIds));
        }
        if(isAdmin >= 0){
            cache.put("isAdmin", isAdmin == 1 ? true : false);
        }
        cacheUtil.set(cacheKey, cache);
    }

    /**
     * 重置系统下所有角色的权限
     * */
    @Async("taskExecutor")
    public void updateAppRoleCache(String aid){
        // 读取角色
        var qw = new QueryWrapper<IamRole>();
        qw.lambda().eq(IamRole::getAppId, aid);
        var roles = roleService.getList(qw);
        if(roles.size() > 0){
            roles.stream().forEach(x -> {
                updateRolePermission(x.getId());
            });
        }
    }
}
